package yieldCurve;

import java.util.Calendar;
import java.util.GregorianCalendar;


public class Date extends GregorianCalendar{
	/**
	 * input: year-month-day
	 * output: deltaT
	 */
	
	private static final long serialVersionUID = 1L;
	
	public Date(int year, int month, int day) {
		super(year,month-1,day);
	}
	
	public Date(){//today
		super();
	}

	
	public static double getDeltaT_day(Date fromDate, int numOfDay){
		Date toDate;
		
		toDate = (Date)fromDate.clone();
		toDate.add(Calendar.DAY_OF_MONTH, numOfDay);
		toDate = businessDay(toDate);	
		
		return getDeltaT(fromDate,toDate);
	}
	
	public double getDeltaT_day(int numOfDay) {
		Date toDate = (Date) this.clone();
		toDate.add(DAY_OF_MONTH, numOfDay);
		toDate = businessDay(toDate);
		return getDeltaT(this, toDate);
	}
	
	public static Date getToDate_day(Date fromDate, int numOfDay){
		Date toDate;
		
		toDate = (Date)fromDate.clone();
		toDate.add(Calendar.DAY_OF_MONTH, numOfDay);
		toDate = businessDay(toDate);
		
		return toDate;
	}
	
	public Date getToDate_day(int numOfDay){
		Date toDate;
		
		toDate = (Date)this.clone();
		toDate.add(Calendar.DAY_OF_MONTH, numOfDay);
		toDate = businessDay(toDate);
		
		return toDate;
	}
	
	public double getDeltaT_month(int numOfMonth) {
		Date toDate = (Date)this.clone();
		
		toDate.add(MONTH, numOfMonth);
		toDate = businessDay(toDate);
		
		return getDeltaT(this, toDate);
	}

	public static double getDeltaT_month(Date fromDate, int numOfMonth){

		Date toDate;
		
		toDate = (Date)fromDate.clone();	
		toDate.add(Calendar.MONTH, numOfMonth);
		toDate = businessDay(toDate);
		
		return getDeltaT(fromDate,toDate);
	}
	
	public static Date getToDate_month(Date fromDate, int numOfMonth){

		Date toDate;
		
		toDate = (Date)fromDate.clone();
		toDate.add(Calendar.MONTH, numOfMonth);
		toDate = businessDay(toDate);
		
		return toDate;
	}

	public Date getToDate_month(int numOfMonth){
		Date toDate;

		toDate = (Date)this.clone();
		toDate.add(Calendar.MONTH, numOfMonth);
		toDate = businessDay(toDate);

		return toDate;
	}

	public static double getDeltaT_year(Date fromDate, int numOfYear){
		Date toDate;
		
		toDate = (Date)fromDate.clone();	
		toDate.add(Calendar.YEAR, numOfYear);		
		toDate = businessDay(toDate);
		
		return getDeltaT(fromDate,toDate);	
	}
	
	public double getDeltaT_year(int numOfYear) {
		Date toDate = (Date)this.clone();
		toDate.add(YEAR, numOfYear);
		toDate = businessDay(toDate);
		return getDeltaT(this, toDate);
	}
	
	public static Date getToDate_year(Date fromDate, int numOfYear){
		Date toDate;
		
		toDate = (Date)fromDate.clone();
		toDate.add(Calendar.YEAR, numOfYear);
		toDate = businessDay(toDate);
		
		return toDate;	
	}
	
	public Date getToDate_year(int numOfYear){
		Date toDate;
		toDate = (Date)this.clone();
		toDate.add(Calendar.YEAR, numOfYear);
		toDate = businessDay(toDate);
		return toDate;	
	}
	
	/** if the date is non-business day
	 * find the next business day of it
	 * @param date Date to check
	 * @return Next business date
	 */	
	public static Date businessDay(Date date) {

		int day_of_week = date.get(Calendar.DAY_OF_WEEK);
		if (day_of_week == 1){//isSunday
			date.add(Calendar.DAY_OF_MONTH, 1);
		}
		else if (day_of_week == 7){//isSaturday
			date.add(Calendar.DAY_OF_MONTH,2);
		}
		return date;
	}
	
	public static double getDeltaT(Date fromDate, Date toDate) {
		int day_of_year_today = fromDate.get(Calendar.DAY_OF_YEAR);
		int day_of_year_toDate = toDate.get(Calendar.DAY_OF_YEAR);

		if(toDate.get(Calendar.YEAR) > fromDate.get(Calendar.YEAR)){
			int today_to_year_end = 365 - fromDate.get(Calendar.DAY_OF_YEAR);
			int beginning_year_to_toDate = toDate.get(Calendar.DAY_OF_YEAR);
			int days = today_to_year_end + beginning_year_to_toDate + (toDate.get(Calendar.YEAR) - fromDate.get(Calendar.YEAR) -1)*365;
			return (double)days/365;
			//
		}
		else{
			return ((double)day_of_year_toDate - (double)day_of_year_today)/365;
		}
	}
	
	public String toString() {
		String str = "";
		str+=get(Calendar.YEAR);
		str+="-";
		str+=get(Calendar.MONTH)+1;
		str+="-";
		str+=get(Calendar.DAY_OF_MONTH);
		return str;
	}
	
	/** Test function
	 * 
	 * @param args none supported
	 */
	static public void main(String args[]){
		Date today = new Date();
		System.out.println(today);
//		System.out.println("..."+today.get(Calendar.DAY_OF_YEAR)+" "+today.get(Calendar.MONTH));	
	}
}
